home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / Delphi 3.0 / DATA.Z / dialogs.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-01-29  |  50.4 KB  |  1,712 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Delphi Visual Component Library                 }
  5. {                                                       }
  6. {       Copyright (c) 1995,97 Borland International     }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit Dialogs;
  11.  
  12. {$R-}
  13.  
  14. interface
  15.  
  16. uses Windows, Messages, SysUtils, CommDlg, Classes, Graphics, Controls,
  17.   Forms, StdCtrls;
  18.  
  19. const
  20.  
  21. { Maximum number of custom colors in color dialog }
  22.  
  23.   MaxCustomColors = 16;
  24.  
  25. type
  26.  
  27. { TCommonDialog }
  28.  
  29.   TCommonDialog = class(TComponent)
  30.   private
  31.     FCtl3D: Boolean;
  32.     FDefWndProc: Pointer;
  33.     FHelpContext: THelpContext;
  34.     FHandle: HWnd;
  35.     FObjectInstance: Pointer;
  36.     FTemplate: PChar;
  37.     FOnClose: TNotifyEvent;
  38.     FOnShow: TNotifyEvent;
  39.   protected
  40.     procedure WndProc(var Message: TMessage); virtual;
  41.     function Message(var Msg: TMessage): Boolean; virtual;
  42.     function TaskModalDialog(DialogFunc: Pointer; var DialogData): Bool; virtual;
  43.     procedure DoClose; dynamic;
  44.     procedure DoShow; dynamic;
  45.     function Execute: Boolean; virtual; abstract;
  46.     property Template: PChar read FTemplate write FTemplate;
  47.   public
  48.     constructor Create(AOwner: TComponent); override;
  49.     destructor Destroy; override;
  50.     property Handle: HWnd read FHandle;
  51.   published
  52.     property Ctl3D: Boolean read FCtl3D write FCtl3D default True;
  53.     property HelpContext: THelpContext read FHelpContext write FHelpContext default 0;
  54.     property OnClose: TNotifyEvent read FOnClose write FOnClose;
  55.     property OnShow: TNotifyEvent read FOnShow write FOnShow;
  56.   end;
  57.  
  58. { TOpenDialog }
  59.  
  60.   TOpenOption = (ofReadOnly, ofOverwritePrompt, ofHideReadOnly,
  61.     ofNoChangeDir, ofShowHelp, ofNoValidate, ofAllowMultiSelect,
  62.     ofExtensionDifferent, ofPathMustExist, ofFileMustExist, ofCreatePrompt,
  63.     ofShareAware, ofNoReadOnlyReturn, ofNoTestFileCreate, ofNoNetworkButton,
  64.     ofNoLongNames, ofOldStyleDialog, ofNoDereferenceLinks);
  65.   TOpenOptions = set of TOpenOption;
  66.  
  67.   TFileEditStyle = (fsEdit, fsComboBox);
  68.  
  69.   TOpenDialog = class(TCommonDialog)
  70.   private
  71.     FHistoryList: TStrings;
  72.     FOptions: TOpenOptions;
  73.     FFilter: string;
  74.     FFilterIndex: Integer;
  75.     FInitialDir: string;
  76.     FTitle: string;
  77.     FDefaultExt: string;
  78.     FFileName: TFileName;
  79.     FFiles: TStrings;
  80.     FFileEditStyle: TFileEditStyle;
  81.     FOnSelectionChange: TNotifyEvent;
  82.     FOnFolderChange: TNotifyEvent;
  83.     FOnTypeChange: TNotifyEvent;
  84.     function GetFileName: string;
  85.     procedure ReadFileEditStyle(Reader: TReader);
  86.     procedure SetHistoryList(Value: TStrings);
  87.     procedure SetInitialDir(const Value: string);
  88.     procedure WndProc(var Message: TMessage); override;
  89.   protected
  90.     procedure DefineProperties(Filer: TFiler); override;
  91.     function DoExecute(Func: Pointer): Bool;
  92.     procedure DoSelectionChange; dynamic;
  93.     procedure DoFolderChange; dynamic;
  94.     procedure DoTypeChange; dynamic;
  95.     function GetStaticRect: TRect; virtual;
  96.   public
  97.     constructor Create(AOwner: TComponent); override;
  98.     destructor Destroy; override;
  99.     function Execute: Boolean; override;
  100.     property FileEditStyle: TFileEditStyle read FFileEditStyle write FFileEditStyle;
  101.     property Files: TStrings read FFiles;
  102.     property HistoryList: TStrings read FHistoryList write SetHistoryList;
  103.   published
  104.     property DefaultExt: string read FDefaultExt write FDefaultExt;
  105.     property FileName: TFileName read GetFileName write FFileName;
  106.     property Filter: string read FFilter write FFilter;
  107.     property FilterIndex: Integer read FFilterIndex write FFilterIndex default 1;
  108.     property InitialDir: string read FInitialDir write SetInitialDir;
  109.     property Options: TOpenOptions read FOptions write FOptions default [];
  110.     property Title: string read FTitle write FTitle;
  111.     property OnFolderChange: TNotifyEvent read FOnFolderChange write FOnFolderChange;
  112.     property OnSelectionChange: TNotifyEvent read FOnSelectionChange write FOnSelectionChange;
  113.     property OnTypeChange: TNotifyEvent read FOnTypeChange write FOnTypeChange;
  114.   end;
  115.  
  116. { TSaveDialog }
  117.  
  118.   TSaveDialog = class(TOpenDialog)
  119.     function Execute: Boolean; override;
  120.   end;
  121.  
  122. { TColorDialog }
  123.  
  124.   TColorDialogOption = (cdFullOpen, cdPreventFullOpen, cdShowHelp,
  125.     cdSolidColor, cdAnyColor);
  126.   TColorDialogOptions = set of TColorDialogOption;
  127.  
  128.   TCustomColors = array[0..MaxCustomColors - 1] of Longint;
  129.  
  130.   TColorDialog = class(TCommonDialog)
  131.   private
  132.     FColor: TColor;
  133.     FOptions: TColorDialogOptions;
  134.     FCustomColors: TStrings;
  135.     procedure SetCustomColors(Value: TStrings);
  136.   public
  137.     constructor Create(AOwner: TComponent); override;
  138.     destructor Destroy; override;
  139.     function Execute: Boolean; override;
  140.   published
  141.     property Color: TColor read FColor write FColor default clBlack;
  142.     property Ctl3D default False;
  143.     property CustomColors: TStrings read FCustomColors write SetCustomColors;
  144.     property Options: TColorDialogOptions read FOptions write FOptions default [];
  145.   end;
  146.  
  147. { TFontDialog }
  148.  
  149.   TFontDialogOption = (fdAnsiOnly, fdTrueTypeOnly, fdEffects,
  150.     fdFixedPitchOnly, fdForceFontExist, fdNoFaceSel, fdNoOEMFonts,
  151.     fdNoSimulations, fdNoSizeSel, fdNoStyleSel,  fdNoVectorFonts,
  152.     fdShowHelp, fdWysiwyg, fdLimitSize, fdScalableOnly, fdApplyButton);
  153.   TFontDialogOptions = set of TFontDialogOption;
  154.  
  155.   TFontDialogDevice = (fdScreen, fdPrinter, fdBoth);
  156.  
  157.   TFDApplyEvent = procedure(Sender: TObject; Wnd: HWND) of object;
  158.  
  159.   TFontDialog = class(TCommonDialog)
  160.   private
  161.     FFont: TFont;
  162.     FDevice: TFontDialogDevice;
  163.     FOptions: TFontDialogOptions;
  164.     FOnApply: TFDApplyEvent;
  165.     FMinFontSize: Integer;
  166.     FMaxFontSize: Integer;
  167.     procedure DoApply(Wnd: HWND);
  168.     procedure SetFont(Value: TFont);
  169.     procedure UpdateFromLogFont(const LogFont: TLogFont);
  170.   protected
  171.     procedure Apply(Wnd: HWND); dynamic;
  172.   public
  173.     constructor Create(AOwner: TComponent); override;
  174.     destructor Destroy; override;
  175.     function Execute: Boolean; override;
  176.   published
  177.     property Font: TFont read FFont write SetFont;
  178.     property Device: TFontDialogDevice read FDevice write FDevice default fdScreen;
  179.     property MinFontSize: Integer read FMinFontSize write FMinFontSize;
  180.     property MaxFontSize: Integer read FMaxFontSize write FMaxFontSize;
  181.     property Options: TFontDialogOptions read FOptions write FOptions default [fdEffects];
  182.     property OnApply: TFDApplyEvent read FOnApply write FOnApply;
  183.   end;
  184.  
  185. { TPrinterSetupDialog }
  186.  
  187.   TPrinterSetupDialog = class(TCommonDialog)
  188.   public
  189.     function Execute: Boolean; override;
  190.   end;
  191.  
  192. { TPrintDialog }
  193.  
  194.   TPrintRange = (prAllPages, prSelection, prPageNums);
  195.   TPrintDialogOption = (poPrintToFile, poPageNums, poSelection, poWarning,
  196.     poHelp, poDisablePrintToFile);
  197.   TPrintDialogOptions = set of TPrintDialogOption;
  198.  
  199.   TPrintDialog = class(TCommonDialog)
  200.   private
  201.     FFromPage: Integer;
  202.     FToPage: Integer;
  203.     FCollate: Boolean;
  204.     FOptions: TPrintDialogOptions;
  205.     FPrintToFile: Boolean;
  206.     FPrintRange: TPrintRange;
  207.     FMinPage: Integer;
  208.     FMaxPage: Integer;
  209.     FCopies: Integer;
  210.     procedure SetNumCopies(Value: Integer);
  211.   public
  212.     function Execute: Boolean; override;
  213.   published
  214.     property Collate: Boolean read FCollate write FCollate default False;
  215.     property Copies: Integer read FCopies write SetNumCopies default 0;
  216.     property FromPage: Integer read FFromPage write FFromPage default 0;
  217.     property MinPage: Integer read FMinPage write FMinPage default 0;
  218.     property MaxPage: Integer read FMaxPage write FMaxPage default 0;
  219.     property Options: TPrintDialogOptions read FOptions write FOptions default [];
  220.     property PrintToFile: Boolean read FPrintToFile write FPrintToFile default False;
  221.     property PrintRange: TPrintRange read FPrintRange write FPrintRange default prAllPages;
  222.     property ToPage: Integer read FToPage write FToPage default 0;
  223.   end;
  224.  
  225. { TFindDialog }
  226.  
  227.   TFindOption = (frDown, frFindNext, frHideMatchCase, frHideWholeWord,
  228.     frHideUpDown, frMatchCase, frDisableMatchCase, frDisableUpDown,
  229.     frDisableWholeWord, frReplace, frReplaceAll, frWholeWord, frShowHelp);
  230.   TFindOptions = set of TFindOption;
  231.  
  232.   TFindReplaceFunc = function(var FindReplace: TFindReplace): HWnd stdcall;
  233.  
  234.   TFindDialog = class(TCommonDialog)
  235.   private
  236.     FOptions: TFindOptions;
  237.     FPosition: TPoint;
  238.     FFindReplaceFunc: TFindReplaceFunc;
  239.     FRedirector: TWinControl;
  240.     FOnFind: TNotifyEvent;
  241.     FOnReplace: TNotifyEvent;
  242.     FFindHandle: HWnd;
  243.     FFindReplace: TFindReplace;
  244.     FFindText: array[0..255] of Char;
  245.     FReplaceText: array[0..255] of Char;
  246.     function GetFindText: string;
  247.     function GetLeft: Integer;
  248.     function GetPosition: TPoint;
  249.     function GetReplaceText: string;
  250.     function GetTop: Integer;
  251.     procedure SetFindText(const Value: string);
  252.     procedure SetLeft(Value: Integer);
  253.     procedure SetPosition(const Value: TPoint);
  254.     procedure SetReplaceText(const Value: string);
  255.     procedure SetTop(Value: Integer);
  256.   protected
  257.     function Message(var Msg: TMessage): Boolean; override;
  258.     procedure Find; dynamic;
  259.     procedure Replace; dynamic;
  260.   public
  261.     constructor Create(AOwner: TComponent); override;
  262.     destructor Destroy; override;
  263.     procedure CloseDialog;
  264.     function Execute: Boolean; override;
  265.     property Left: Integer read GetLeft write SetLeft;
  266.     property Position: TPoint read GetPosition write SetPosition;
  267.     property Top: Integer read GetTop write SetTop;
  268.   published
  269.     property FindText: string read GetFindText write SetFindText;
  270.     property Options: TFindOptions read FOptions write FOptions default [frDown];
  271.     property OnFind: TNotifyEvent read FOnFind write FOnFind;
  272.   end;
  273.  
  274. { TReplaceDialog }
  275.  
  276.   TReplaceDialog = class(TFindDialog)
  277.   public
  278.     constructor Create(AOwner: TComponent); override;
  279.   published
  280.     property ReplaceText: string read GetReplaceText write SetReplaceText;
  281.     property OnReplace: TNotifyEvent read FOnReplace write FOnReplace;
  282.   end;
  283.  
  284. { Message dialog }
  285.  
  286. type
  287.   TMsgDlgType = (mtWarning, mtError, mtInformation, mtConfirmation, mtCustom);
  288.   TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore,
  289.     mbAll, mbNoToAll, mbYesToAll, mbHelp);
  290.   TMsgDlgButtons = set of TMsgDlgBtn;
  291.  
  292. const
  293.   mbYesNoCancel = [mbYes, mbNo, mbCancel];
  294.   mbOKCancel = [mbOK, mbCancel];
  295.   mbAbortRetryIgnore = [mbAbort, mbRetry, mbIgnore];
  296.  
  297. function CreateMessageDialog(const Msg: string; DlgType: TMsgDlgType;
  298.   Buttons: TMsgDlgButtons): TForm;
  299.  
  300. function MessageDlg(const Msg: string; DlgType: TMsgDlgType;
  301.   Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
  302. function MessageDlgPos(const Msg: string; DlgType: TMsgDlgType;
  303.   Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer): Integer;
  304.  
  305. procedure ShowMessage(const Msg: string);
  306. procedure ShowMessageFmt(const Msg: string; Params: array of const);
  307. procedure ShowMessagePos(const Msg: string; X, Y: Integer);
  308.  
  309. { Input dialog }
  310.  
  311. function InputBox(const ACaption, APrompt, ADefault: string): string;
  312. function InputQuery(const ACaption, APrompt: string;
  313.   var Value: string): Boolean;
  314.  
  315. implementation
  316.  
  317. uses ExtCtrls, Consts, Printers, Dlgs, commctrl;
  318.  
  319. { Private globals }
  320.  
  321. var
  322.   CreationControl: TCommonDialog = nil;
  323.   HelpMsg: Integer;
  324.   FindMsg: Integer;
  325.   WndProcPtrAtom: TAtom = 0;
  326.   HookCtl3D: Boolean;
  327.  
  328. { Center the given window on the screen }
  329.  
  330. procedure CenterWindow(Wnd: HWnd);
  331. var
  332.   Rect: TRect;
  333. begin
  334.   GetWindowRect(Wnd, Rect);
  335.   SetWindowPos(Wnd, 0,
  336.     (GetSystemMetrics(SM_CXSCREEN) - Rect.Right + Rect.Left) div 2,
  337.     (GetSystemMetrics(SM_CYSCREEN) - Rect.Bottom + Rect.Top) div 3,
  338.     0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
  339. end;
  340.  
  341. { Generic dialog hook. Centers the dialog on the screen in response to
  342.   the WM_INITDIALOG message }
  343.  
  344. function DialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
  345. begin
  346.   Result := 0;
  347.   case Msg of
  348.     WM_INITDIALOG:
  349.       begin
  350.         if HookCtl3D then
  351.         begin
  352.           Subclass3DDlg(Wnd, CTL3D_ALL);
  353.           SetAutoSubClass(True);
  354.         end;
  355.         CenterWindow(Wnd);
  356.         CreationControl.FHandle := Wnd;
  357.         CreationControl.FDefWndProc := Pointer(SetWindowLong(Wnd, GWL_WNDPROC,
  358.           Longint(CreationControl.FObjectInstance)));
  359.         CallWindowProc(CreationControl.FObjectInstance, Wnd, Msg, WParam, LParam);
  360.       end;
  361.     WM_DESTROY:
  362.       if HookCtl3D then SetAutoSubClass(False);
  363.   end;
  364. end;
  365.  
  366. { TCommonDialog }
  367.  
  368. constructor TCommonDialog.Create(AOwner: TComponent);
  369. begin
  370.   inherited Create(AOwner);
  371.   FCtl3D := True;
  372.   FObjectInstance := MakeObjectInstance(WndProc);
  373. end;
  374.  
  375. destructor TCommonDialog.Destroy;
  376. begin
  377.   if FObjectInstance <> nil then FreeObjectInstance(FObjectInstance);
  378.   inherited Destroy;
  379. end;
  380.  
  381. function TCommonDialog.Message(var Msg: TMessage): Boolean;
  382. begin
  383.   Result := False;
  384.   if (Msg.Msg = HelpMsg) and (FHelpContext <> 0) then
  385.   begin
  386.     Application.HelpContext(FHelpContext);
  387.     Result := True;
  388.   end;
  389. end;
  390.  
  391. procedure TCommonDialog.WndProc(var Message: TMessage);
  392. begin
  393.   with Message do
  394.   begin
  395.     case Msg of
  396.       WM_INITDIALOG:
  397.         begin
  398.           CreationControl := nil;
  399.           DoShow;
  400.           { Prevent any further processing }
  401.           Result := 0;
  402.           Exit;
  403.         end;
  404.       WM_DESTROY:
  405.         begin
  406.           DoClose;
  407.           if HookCtl3D then SetAutoSubClass(False);
  408.           FHandle := 0;
  409.         end;
  410.     end;
  411.     Result := CallWindowProc(FDefWndProc, FHandle, Msg, WParam, LParam);
  412.   end;
  413. end;
  414.  
  415. function TCommonDialog.TaskModalDialog(DialogFunc: Pointer; var DialogData): Bool;
  416. type
  417.   TDialogFunc = function(var DialogData): Bool stdcall;
  418. var
  419.   ActiveWindow: HWnd;
  420.   WindowList: Pointer;
  421. begin
  422.   ActiveWindow := GetActiveWindow;
  423.   WindowList := DisableTaskWindows(0);
  424.   try
  425.     Application.HookMainWindow(Message);
  426.     try
  427.       CreationControl := Self;
  428.       Result := TDialogFunc(DialogFunc)(DialogData);
  429.     finally
  430.       Application.UnhookMainWindow(Message);
  431.     end;
  432.   finally
  433.     EnableTaskWindows(WindowList);
  434.     SetActiveWindow(ActiveWindow);
  435.   end;
  436. end;
  437.  
  438. procedure TCommonDialog.DoClose;
  439. begin
  440.   if Assigned(FOnClose) then FOnClose(Self);
  441. end;
  442.  
  443. procedure TCommonDialog.DoShow;
  444. begin
  445.   if Assigned(FOnShow) then FOnShow(Self);
  446. end;
  447.  
  448. { Open and Save dialog routines }
  449.  
  450. function ExplorerHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
  451. begin
  452.   Result := 0;
  453.   if Msg = WM_INITDIALOG then
  454.   begin
  455.     CreationControl.FHandle := Wnd;
  456.     CreationControl.FDefWndProc := Pointer(SetWindowLong(Wnd, GWL_WNDPROC,
  457.       Longint(CreationControl.FObjectInstance)));
  458.     CallWindowProc(CreationControl.FObjectInstance, Wnd, Msg, WParam, LParam);
  459.   end
  460.   else if (Msg = WM_NOTIFY) and (POFNotify(LParam)^.hdr.code = CDN_INITDONE) then
  461.     CenterWindow(GetWindowLong(Wnd, GWL_HWNDPARENT));
  462. end;
  463.  
  464. { TOpenDialog }
  465.  
  466. constructor TOpenDialog.Create(AOwner: TComponent);
  467. begin
  468.   inherited Create(AOwner);
  469.   FHistoryList := TStringList.Create;
  470.   FFiles := TStringList.Create;
  471.   FFilterIndex := 1;
  472.   FFileEditStyle := fsEdit;
  473. end;
  474.  
  475. destructor TOpenDialog.Destroy;
  476. begin
  477.   FFiles.Free;
  478.   FHistoryList.Free;
  479.   inherited Destroy;
  480. end;
  481.  
  482. procedure TOpenDialog.WndProc(var Message: TMessage);
  483. begin
  484.   Message.Result := 0;
  485.   { If not ofOldStyleDialog then Show on CDN_INITDONE, not WM_INITDIALOG }
  486.   if (Message.Msg = WM_INITDIALOG) and not (ofOldStyleDialog in Options) then Exit
  487.   else if (Message.Msg = WM_NOTIFY) then
  488.     case (POFNotify(Message.LParam)^.hdr.code) of
  489.       CDN_INITDONE: DoShow;
  490.       CDN_SELCHANGE: DoSelectionChange;
  491.       CDN_FOLDERCHANGE: DoFolderChange;
  492.       CDN_TYPECHANGE: DoTypeChange;
  493.     end;
  494.   inherited WndProc(Message);
  495. end;
  496.  
  497. procedure TOpenDialog.DoSelectionChange;
  498. begin
  499.   if Assigned(FOnSelectionChange) then FOnSelectionChange(Self);
  500. end;
  501.  
  502. procedure TOpenDialog.DoFolderChange;
  503. begin
  504.   if Assigned(FOnFolderChange) then FOnFolderChange(Self);
  505. end;
  506.  
  507. procedure TOpenDialog.DoTypeChange;
  508. begin
  509.   if Assigned(FOnTypeChange) then FOnTypeChange(Self);
  510. end;
  511.  
  512. procedure TOpenDialog.ReadFileEditStyle(Reader: TReader);
  513. begin
  514.   { Ignore FileEditStyle }
  515.   Reader.ReadIdent;
  516. end;
  517.  
  518. procedure TOpenDialog.DefineProperties(Filer: TFiler);
  519. begin
  520.   inherited DefineProperties(Filer);
  521.   Filer.DefineProperty('FileEditStyle', ReadFileEditStyle, nil, False);
  522. end;
  523.  
  524. function TOpenDialog.DoExecute(Func: Pointer): Bool;
  525. const
  526.   MultiSelectBufferSize = 8192;
  527.   OpenOptions: array [TOpenOption] of Longint = (
  528.     OFN_READONLY, OFN_OVERWRITEPROMPT, OFN_HIDEREADONLY,
  529.     OFN_NOCHANGEDIR, OFN_SHOWHELP, OFN_NOVALIDATE, OFN_ALLOWMULTISELECT,
  530.     OFN_EXTENSIONDIFFERENT, OFN_PATHMUSTEXIST, OFN_FILEMUSTEXIST,
  531.     OFN_CREATEPROMPT, OFN_SHAREAWARE, OFN_NOREADONLYRETURN,
  532.     OFN_NOTESTFILECREATE, OFN_NONETWORKBUTTON, OFN_NOLONGNAMES,
  533.     OFN_EXPLORER, OFN_NODEREFERENCELINKS);
  534. var
  535.   Option: TOpenOption;
  536.   OpenFilename: TOpenFilename;
  537.   Separator: Char;
  538.  
  539.   function AllocFilterStr(const S: string): string;
  540.   var
  541.     P: PChar;
  542.   begin
  543.     Result := '';
  544.     if S <> '' then
  545.     begin
  546.       Result := S + #0;  // double null terminators
  547.       P := AnsiStrScan(PChar(Result), '|');
  548.       while P <> nil do
  549.       begin
  550.         P^ := #0;
  551.         Inc(P);
  552.         P := AnsiStrScan(P, '|');
  553.       end;
  554.     end;
  555.   end;
  556.  
  557.   function ExtractFileName(P: PChar; var S: string): PChar;
  558.   begin
  559.     Result := AnsiStrScan(P, Separator);
  560.     if Result = nil then
  561.     begin
  562.       S := P;
  563.       Result := StrEnd(P);
  564.     end
  565.     else
  566.     begin
  567.       SetString(S, P, Result - P);
  568.       Inc(Result);
  569.     end;
  570.   end;
  571.  
  572.   procedure ExtractFileNames(P: PChar);
  573.   var
  574.     DirName, FileName: string;
  575.   begin
  576.     P := ExtractFileName(P, DirName);
  577.     P := ExtractFileName(P, FileName);
  578.     if FileName = '' then
  579.       FFiles.Add(DirName)
  580.     else
  581.     begin
  582.       if AnsiLastChar(DirName)^ <> '\' then
  583.         DirName := DirName + '\';
  584.       repeat
  585.         if (FileName[1] <> '\') and ((Length(FileName) <= 3) or
  586.           (FileName[2] <> ':') or (FileName[3] <> '\')) then
  587.           FileName := DirName + FileName;
  588.         FFiles.Add(FileName);
  589.         P := ExtractFileName(P, FileName);
  590.       until FileName = '';
  591.     end;
  592.   end;
  593.  
  594. var
  595.   TempFilter, TempFilename, TempExt: string;
  596. begin
  597.   Separator := #0;
  598.   if (ofAllowMultiSelect in FOptions) and
  599.     ((ofOldStyleDialog in FOptions) or not NewStyleControls) then
  600.     Separator := ' ';
  601.   FFiles.Clear;
  602.   FillChar(OpenFileName, SizeOf(OpenFileName), 0);
  603.   with OpenFilename do
  604.   begin
  605.     lStructSize := SizeOf(TOpenFilename);
  606.     hInstance := SysInit.HInstance;
  607.     TempFilter := AllocFilterStr(FFilter);
  608.     lpstrFilter := PChar(TempFilter);
  609.     nFilterIndex := FFilterIndex;
  610.     if ofAllowMultiSelect in FOptions then
  611.       nMaxFile := MultiSelectBufferSize else
  612.       nMaxFile := MAX_PATH;
  613.     SetLength(TempFilename, nMaxFile + 2);
  614.     lpstrFile := PChar(TempFilename);
  615.     FillChar(lpstrFile^, nMaxFile + 2, 0);
  616.     StrLCopy(lpstrFile, PChar(FFileName), nMaxFile);
  617.     lpstrInitialDir := PChar(FInitialDir);
  618.     lpstrTitle := PChar(FTitle);
  619.     HookCtl3D := FCtl3D;
  620.     Flags := OFN_ENABLEHOOK;
  621.     for Option := Low(Option) to High(Option) do
  622.       if Option in FOptions then
  623.         Flags := Flags or OpenOptions[Option];
  624.     if NewStyleControls then
  625.       Flags := Flags xor OFN_EXPLORER
  626.     else
  627.       Flags := Flags and not OFN_EXPLORER;
  628.     TempExt := FDefaultExt;
  629.     if (TempExt = '') and (Flags and OFN_EXPLORER = 0) then
  630.     begin
  631.       TempExt := ExtractFileExt(FFilename);
  632.       Delete(TempExt, 1, 1);
  633.     end;
  634.     if TempExt <> '' then lpstrDefExt := PChar(TempExt);
  635.     if (ofOldStyleDialog in Options) or not NewStyleControls then
  636.       lpfnHook := DialogHook
  637.     else
  638.     begin
  639.       lpfnHook := ExplorerHook;
  640.     end;
  641.       if Template <> nil then
  642.       begin
  643.         Flags := Flags or OFN_ENABLETEMPLATE;
  644.         lpTemplateName := Template;
  645.       end;
  646.     hWndOwner := Application.Handle;
  647.     Result := TaskModalDialog(Func, OpenFileName);
  648.     if Result then
  649.     begin
  650.       if ofAllowMultiSelect in FOptions then
  651.       begin
  652.         ExtractFileNames(lpstrFile);
  653.         FFileName := FFiles[0];
  654.       end else
  655.       begin
  656.         ExtractFileName(lpstrFile, FFileName);
  657.         FFiles.Add(FFileName);
  658.       end;
  659.       if (Flags and OFN_EXTENSIONDIFFERENT) <> 0 then
  660.         Include(FOptions, ofExtensionDifferent) else
  661.         Exclude(FOptions, ofExtensionDifferent);
  662.       if (Flags and OFN_READONLY) <> 0 then
  663.         Include(FOptions, ofReadOnly) else
  664.         Exclude(FOptions, ofReadOnly);
  665.       FFilterIndex := nFilterIndex;
  666.     end;
  667.   end;
  668. end;
  669.  
  670. function TOpenDialog.GetStaticRect: TRect;
  671. begin
  672.   if FHandle <> 0 then
  673.   begin
  674.     if not (ofOldStyleDialog in Options) then
  675.     begin
  676.       GetWindowRect(GetDlgItem(FHandle, stc32), Result);
  677.       MapWindowPoints(0, FHandle, Result, 2);
  678.     end
  679.     else GetClientRect(FHandle, Result)
  680.   end
  681.   else Result := Rect(0,0,0,0);
  682. end;
  683.  
  684. function TOpenDialog.GetFileName: string;
  685. var
  686.   DialogHandle, ListHandle: THandle;
  687.   Len: Integer;
  688.   Path: array[0..MAX_PATH] of Char;
  689.   PathPos: PChar;
  690.   Item: TLVItem;
  691. begin
  692.   if NewStyleControls and (FHandle <> 0) then
  693.   begin
  694.     DialogHandle := GetParent(FHandle);
  695.     Len := SendMessage(DialogHandle, CDM_GETFOLDERPATH, SizeOf(Path), Integer(@Path));
  696.     if (Len > 0) and (Len <= SizeOf(Path)) then
  697.     begin
  698.       PathPos := AnsiStrLastChar(Path);
  699.       if PathPos^ <> '\' then StrCat(PathPos, '\');
  700.       PathPos := StrEnd(PathPos);
  701.     end
  702.     else PathPos := Path;
  703.     { CDM_GETFILEPATH does not retrieve folder names, so here we attempt to
  704.       retrieve the text of the focused item (file or folder) directly from the
  705.       explorer-style ListView control (static id 'lst2'). }
  706.     ListHandle := GetDlgItem(GetDlgItem(DialogHandle, lst2), 1);
  707.     if ListHandle <> 0 then
  708.     begin
  709.       with Item do
  710.       begin
  711.         mask := LVIF_TEXT;
  712.         iItem := SendMessage(ListHandle, LVM_GETNEXTITEM, -1, LVNI_ALL or LVNI_FOCUSED);
  713.         iSubItem := 0;
  714.         pszText := PathPos;
  715.         cchTextMax := SizeOf(Path) - (Integer(PathPos) - Integer(@Path));
  716.       end;
  717.       { If we didn't retrieve an item then nullify the entire result }
  718.       if SendMessage(ListHandle, LVM_GETITEM, 0, Integer(@Item)) = 0 then
  719.         Path[0] := #0;
  720.     end
  721.     else SendMessage(DialogHandle, CDM_GETFILEPATH, SizeOf(Path), Integer(@Path));
  722.     Result := StrPas(Path);
  723.   end
  724.   else Result := FFileName;
  725. end;
  726.  
  727. procedure TOpenDialog.SetHistoryList(Value: TStrings);
  728. begin
  729.   FHistoryList.Assign(Value);
  730. end;
  731.  
  732. procedure TOpenDialog.SetInitialDir(const Value: string);
  733. var
  734.   L: Integer;
  735. begin
  736.   L := Length(Value);
  737.   if (L > 1) and IsPathDelimiter(Value, L)
  738.     and not IsDelimiter(':', Value, L - 1) then Dec(L);
  739.   FInitialDir := Copy(Value, 1, L);
  740. end;
  741.  
  742. function TOpenDialog.Execute: Boolean;
  743. begin
  744.   Result := DoExecute(@GetOpenFileName);
  745. end;
  746.  
  747. { TSaveDialog }
  748.  
  749. function TSaveDialog.Execute: Boolean;
  750. begin
  751.   Result := DoExecute(@GetSaveFileName);
  752. end;
  753.  
  754. { TColorDialog }
  755.  
  756. constructor TColorDialog.Create(AOwner: TComponent);
  757. begin
  758.   inherited Create(AOwner);
  759.   FCustomColors := TStringList.Create;
  760. end;
  761.  
  762. destructor TColorDialog.Destroy;
  763. begin
  764.   FCustomColors.Free;
  765.   inherited Destroy;
  766. end;
  767.  
  768. function TColorDialog.Execute: Boolean;
  769. const
  770.   DialogOptions: array[TColorDialogOption] of LongInt = (
  771.     CC_FULLOPEN, CC_PREVENTFULLOPEN, CC_SHOWHELP, CC_SOLIDCOLOR,
  772.     CC_ANYCOLOR);
  773. var
  774.   ChooseColorRec: TChooseColor;
  775.   Option: TColorDialogOption;
  776.   CustomColorsArray: TCustomColors;
  777.   ColorPrefix, ColorTags: string;
  778.  
  779.   procedure GetCustomColorsArray;
  780.   var
  781.     I: Integer;
  782.   begin
  783.     for I := 0 to MaxCustomColors - 1 do
  784.       FCustomColors.Values[ColorPrefix + ColorTags[I + 1]] :=
  785.         Format('%.6x', [CustomColorsArray[I]]);
  786.   end;
  787.  
  788.   procedure SetCustomColorsArray;
  789.   var
  790.     Value: string;
  791.     I: Integer;
  792.   begin
  793.     for I := 0 to MaxCustomColors - 1 do
  794.     begin
  795.       Value := FCustomColors.Values[ColorPrefix + ColorTags[I + 1]];
  796.       if Value <> '' then
  797.         CustomColorsArray[I] := StrToInt('$' + Value) else
  798.         CustomColorsArray[I] := -1;
  799.     end;
  800.   end;
  801.  
  802. begin
  803.   ColorPrefix := SColorPrefix;
  804.   ColorTags := SColorTags;
  805.   with ChooseColorRec do
  806.   begin
  807.     SetCustomColorsArray;
  808.     lStructSize := SizeOf(ChooseColorRec);
  809.     hInstance := SysInit.HInstance;
  810.     rgbResult := ColorToRGB(FColor);
  811.     lpCustColors := @CustomColorsArray;
  812.     Flags := CC_RGBINIT or CC_ENABLEHOOK;
  813.     for Option := Low(Option) to High(Option) do
  814.       if Option in FOptions then
  815.         Flags := Flags or DialogOptions[Option];
  816.     if Template <> nil then
  817.     begin
  818.       Flags := Flags or CC_ENABLETEMPLATE;
  819.       lpTemplateName := Template;
  820.     end;
  821.     HookCtl3D := FCtl3D;
  822.     lpfnHook := DialogHook;
  823.     hWndOwner := Application.Handle;
  824.     Result := TaskModalDialog(@ChooseColor, ChooseColorRec);
  825.     if Result then
  826.     begin
  827.       FColor := rgbResult;
  828.       GetCustomColorsArray;
  829.     end;
  830.   end;
  831. end;
  832.  
  833. procedure TColorDialog.SetCustomColors(Value: TStrings);
  834. begin
  835.   FCustomColors.Assign(Value);
  836. end;
  837.  
  838. { TFontDialog }
  839.  
  840. const
  841.   IDAPPLYBTN = $402;
  842.  
  843. var
  844.   FontDialog: TFontDialog;
  845.  
  846. function FontDialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
  847. begin
  848.   if (Msg = WM_COMMAND) and (LongRec(WParam).Lo = IDAPPLYBTN) and
  849.     (LongRec(WParam).Hi = BN_CLICKED) then
  850.   begin
  851.     FontDialog.DoApply(Wnd);
  852.     Result := 1;
  853.   end else
  854.     Result := DialogHook(Wnd, Msg, wParam, lParam);
  855. end;
  856.  
  857. constructor TFontDialog.Create(AOwner: TComponent);
  858. begin
  859.   inherited Create(AOwner);
  860.   FFont := TFont.Create;
  861.   FOptions := [fdEffects];
  862. end;
  863.  
  864. destructor TFontDialog.Destroy;
  865. begin
  866.   FFont.Free;
  867.   inherited Destroy;
  868. end;
  869.  
  870. procedure TFontDialog.Apply(Wnd: HWND);
  871. begin
  872.   if Assigned(FOnApply) then FOnApply(Self, Wnd);
  873. end;
  874.  
  875. procedure TFontDialog.DoApply(Wnd: HWND);
  876. const
  877.   IDCOLORCMB = $473;
  878. var
  879.   I: Integer;
  880.   LogFont: TLogFont;
  881. begin
  882.   SendMessage(Wnd, WM_CHOOSEFONT_GETLOGFONT, 0, LongInt(@LogFont));
  883.   UpdateFromLogFont(LogFont);
  884.   I := SendDlgItemMessage(Wnd, IDCOLORCMB, CB_GETCURSEL, 0, 0);
  885.   if I <> CB_ERR then
  886.     Font.Color := SendDlgItemMessage(Wnd, IDCOLORCMB, CB_GETITEMDATA, I, 0);
  887.   try
  888.     Apply(Wnd);
  889.   except
  890.     Application.HandleException(Self);
  891.   end;
  892. end;
  893.  
  894. function TFontDialog.Execute: Boolean;
  895. const
  896.   FontOptions: array[TFontDialogOption] of Longint = (
  897.     CF_ANSIONLY, CF_TTONLY, CF_EFFECTS, CF_FIXEDPITCHONLY, CF_FORCEFONTEXIST,
  898.     CF_NOFACESEL, CF_NOOEMFONTS, CF_NOSIMULATIONS, CF_NOSIZESEL,
  899.     CF_NOSTYLESEL, CF_NOVECTORFONTS, CF_SHOWHELP, CF_WYSIWYG, CF_LIMITSIZE,
  900.     CF_SCALABLEONLY, CF_APPLY);
  901.   Devices: array[TFontDialogDevice] of Longint = (
  902.     CF_SCREENFONTS, CF_PRINTERFONTS, CF_BOTH);
  903. var
  904.   ChooseFontRec: TChooseFont;
  905.   LogFont: TLogFont;
  906.   Option: TFontDialogOption;
  907.   SaveFontDialog: TFontDialog;
  908. begin
  909.   with ChooseFontRec do
  910.   begin
  911.     lStructSize := SizeOf(ChooseFontRec);
  912.     hDC := 0;
  913.     if FDevice <> fdScreen then hDC := Printer.Handle;
  914.     lpLogFont := @LogFont;
  915.     GetObject(Font.Handle, SizeOf(LogFont), @LogFont);
  916.     Flags := Devices[FDevice] or (CF_INITTOLOGFONTSTRUCT or CF_ENABLEHOOK);
  917.     for Option := Low(Option) to High(Option) do
  918.       if Option in FOptions then
  919.         Flags := Flags or FontOptions[Option];
  920.     if Assigned(FOnApply) then Flags := Flags or CF_APPLY;
  921.     if Template <> nil then
  922.     begin
  923.       Flags := Flags or CF_ENABLETEMPLATE;
  924.       lpTemplateName := Template;
  925.     end;
  926.     rgbColors := Font.Color;
  927.     lCustData := 0;
  928.     HookCtl3D := Ctl3D;
  929.     lpfnHook := FontDialogHook;
  930.     nSizeMin := FMinFontSize;
  931.     nSizeMax := FMaxFontSize;
  932.     if nSizeMin > nSizeMax then Flags := Flags and (not CF_LIMITSIZE);
  933.     hWndOwner := Application.Handle;
  934.     SaveFontDialog := FontDialog;
  935.     FontDialog := Self;
  936.     Result := TaskModalDialog(@ChooseFont, ChooseFontRec);
  937.     FontDialog := SaveFontDialog;
  938.     if Result then
  939.     begin
  940.       UpdateFromLogFont(LogFont);
  941.       Font.Color := rgbColors;
  942.     end;
  943.   end;
  944. end;
  945.  
  946. procedure TFontDialog.SetFont(Value: TFont);
  947. begin
  948.   FFont.Assign(Value);
  949. end;
  950.  
  951. procedure TFontDialog.UpdateFromLogFont(const LogFont: TLogFont);
  952. var
  953.   Style: TFontStyles;
  954. begin
  955.   with LogFont do
  956.   begin
  957.     Font.Name := LogFont.lfFaceName;
  958.     Font.Height := LogFont.lfHeight;
  959.     Font.Charset := TFontCharset(LogFont.lfCharSet);
  960.     Style := [];
  961.     with LogFont do
  962.     begin
  963.       if lfWeight > FW_REGULAR then Include(Style, fsBold);
  964.       if lfItalic <> 0 then Include(Style, fsItalic);
  965.       if lfUnderline <> 0 then Include(Style, fsUnderline);
  966.       if lfStrikeOut <> 0 then Include(Style, fsStrikeOut);
  967.     end;
  968.     Font.Style := Style;
  969.   end;
  970. end;
  971.  
  972. { Printer dialog routines }
  973.  
  974. procedure GetPrinter(var DeviceMode, DeviceNames: THandle);
  975. var
  976.   Device, Driver, Port: array[0..79] of char;
  977.   DevNames: PDevNames;
  978.   Offset: PChar;
  979. begin
  980.   Printer.GetPrinter(Device, Driver, Port, DeviceMode);
  981.   if DeviceMode <> 0 then
  982.   begin
  983.     DeviceNames := GlobalAlloc(GHND, SizeOf(TDevNames) +
  984.      StrLen(Device) + StrLen(Driver) + StrLen(Port) + 3);
  985.     DevNames := PDevNames(GlobalLock(DeviceNames));
  986.     try
  987.       Offset := PChar(DevNames) + SizeOf(TDevnames);
  988.       with DevNames^ do
  989.       begin
  990.         wDriverOffset := Longint(Offset) - Longint(DevNames);
  991.         Offset := StrECopy(Offset, Driver) + 1;
  992.         wDeviceOffset := Longint(Offset) - Longint(DevNames);
  993.         Offset := StrECopy(Offset, Device) + 1;
  994.         wOutputOffset := Longint(Offset) - Longint(DevNames);;
  995.         StrCopy(Offset, Port);
  996.       end;
  997.     finally
  998.       GlobalUnlock(DeviceNames);
  999.     end;
  1000.   end;
  1001. end;
  1002.  
  1003. procedure SetPrinter(DeviceMode, DeviceNames: THandle);
  1004. var
  1005.   DevNames: PDevNames;
  1006. begin
  1007.   DevNames := PDevNames(GlobalLock(DeviceNames));
  1008.   try
  1009.     with DevNames^ do
  1010.       Printer.SetPrinter(PChar(DevNames) + wDeviceOffset,
  1011.         PChar(DevNames) + wDriverOffset,
  1012.         PChar(DevNames) + wOutputOffset, DeviceMode);
  1013.   finally
  1014.     GlobalUnlock(DeviceNames);
  1015.     GlobalFree(DeviceNames);
  1016.   end;
  1017. end;
  1018.  
  1019. function CopyData(Handle: THandle): THandle;
  1020. var
  1021.   Src, Dest: PChar;
  1022.   Size: Integer;
  1023. begin
  1024.   if Handle <> 0 then
  1025.   begin
  1026.     Size := GlobalSize(Handle);
  1027.     Result := GlobalAlloc(GHND, Size);
  1028.     if Result <> 0 then
  1029.       try
  1030.         Src := GlobalLock(Handle);
  1031.         Dest := GlobalLock(Result);
  1032.         if (Src <> nil) and (Dest <> nil) then Move(Src^, Dest^, Size);
  1033.       finally
  1034.         GlobalUnlock(Handle);
  1035.         GlobalUnlock(Result);
  1036.       end
  1037.   end
  1038.   else Result := 0;
  1039. end;
  1040.  
  1041. { TPrinterSetupDialog }
  1042.  
  1043. function TPrinterSetupDialog.Execute: Boolean;
  1044. var
  1045.   PrintDlgRec: TPrintDlg;
  1046.   DevHandle: THandle;
  1047. begin
  1048.   FillChar(PrintDlgRec, SizeOf(PrintDlgRec), 0);
  1049.   with PrintDlgRec do
  1050.   begin
  1051.     lStructSize := SizeOf(PrintDlgRec);
  1052.     hInstance := SysInit.HInstance;
  1053.     GetPrinter(DevHandle, hDevNames);
  1054.     hDevMode := CopyData(DevHandle);
  1055.     Flags := PD_ENABLESETUPHOOK or PD_PRINTSETUP;
  1056.     HookCtl3D := Ctl3D;
  1057.     lpfnSetupHook := DialogHook;
  1058.     hWndOwner := Application.Handle;
  1059.     Result := TaskModalDialog(@PrintDlg, PrintDlgRec);
  1060.     if Result then
  1061.       SetPrinter(hDevMode, hDevNames)
  1062.     else begin
  1063.       if hDevMode <> 0 then GlobalFree(hDevMode);
  1064.       if hDevNames <> 0 then GlobalFree(hDevNames);
  1065.     end;
  1066.   end;
  1067. end;
  1068.  
  1069. { TPrintDialog }
  1070.  
  1071. procedure TPrintDialog.SetNumCopies(Value: Integer);
  1072. begin
  1073.   FCopies := Value;
  1074.   Printer.Copies := Value;
  1075. end;
  1076.  
  1077. function TPrintDialog.Execute: Boolean;
  1078. const
  1079.   PrintRanges: array[TPrintRange] of Integer =
  1080.     (PD_ALLPAGES, PD_SELECTION, PD_PAGENUMS);
  1081. var
  1082.   PrintDlgRec: TPrintDlg;
  1083.   DevHandle: THandle;
  1084. begin
  1085.   FillChar(PrintDlgRec, SizeOf(PrintDlgRec), 0);
  1086.   with PrintDlgRec do
  1087.   begin
  1088.     lStructSize := SizeOf(PrintDlgRec);
  1089.     hInstance := SysInit.HInstance;
  1090.     GetPrinter(DevHandle, hDevNames);
  1091.     hDevMode := CopyData(DevHandle);
  1092.     Flags := PrintRanges[FPrintRange] or (PD_ENABLEPRINTHOOK or
  1093.       PD_ENABLESETUPHOOK);
  1094.     if FCollate then Inc(Flags, PD_COLLATE);
  1095.     if not (poPrintToFile in FOptions) then Inc(Flags, PD_HIDEPRINTTOFILE);
  1096.     if not (poPageNums in FOptions) then Inc(Flags, PD_NOPAGENUMS);
  1097.     if not (poSelection in FOptions) then Inc(Flags, PD_NOSELECTION);
  1098.     if poDisablePrintToFile in FOptions then Inc(Flags, PD_DISABLEPRINTTOFILE);
  1099.     if FPrintToFile then Inc(Flags, PD_PRINTTOFILE);
  1100.     if poHelp in FOptions then Inc(Flags, PD_SHOWHELP);
  1101.     if not (poWarning in FOptions) then Inc(Flags, PD_NOWARNING);
  1102.     nFromPage := FFromPage;
  1103.     nToPage := FToPage;
  1104.     nMinPage := FMinPage;
  1105.     nMaxPage := FMaxPage;
  1106.     HookCtl3D := Ctl3D;
  1107.     lpfnPrintHook := DialogHook;
  1108.     lpfnSetupHook := DialogHook;
  1109.     hWndOwner := Application.Handle;
  1110.     Result := TaskModalDialog(@PrintDlg, PrintDlgRec);
  1111.     if Result then
  1112.     begin
  1113.       SetPrinter(hDevMode, hDevNames);
  1114.       FCollate := Flags and PD_COLLATE <> 0;
  1115.       FPrintToFile := Flags and PD_PRINTTOFILE <> 0;
  1116.       if Flags and PD_SELECTION <> 0 then FPrintRange := prSelection else
  1117.         if Flags and PD_PAGENUMS <> 0 then FPrintRange := prPageNums else
  1118.           FPrintRange := prAllPages;
  1119.       FFromPage := nFromPage;
  1120.       FToPage := nToPage;
  1121.       if nCopies = 1 then
  1122.         Copies := Printer.Copies else
  1123.         Copies := nCopies;
  1124.     end
  1125.     else begin
  1126.       if hDevMode <> 0 then GlobalFree(hDevMode);
  1127.       if hDevNames <> 0 then GlobalFree(hDevNames);
  1128.     end;
  1129.   end;
  1130. end;
  1131.  
  1132. { TRedirectorWindow }
  1133. { A redirector window is used to put the find/replace dialog into the
  1134.   ownership chain of a form, but intercept messages that CommDlg.dll sends
  1135.   exclusively to the find/replace dialog's owner.  TRedirectorWindow
  1136.   creates its hidden window handle as owned by the target form, and the
  1137.   find/replace dialog handle is created as owned by the redirector.  The
  1138.   redirector wndproc forwards all messages to the find/replace component.
  1139. }
  1140.  
  1141. type
  1142.   TRedirectorWindow = class(TWinControl)
  1143.   private
  1144.     FFindReplaceDialog: TFindDialog;
  1145.     FFormHandle: THandle;
  1146.     procedure CMRelease(var Message); message CM_Release;
  1147.   protected
  1148.     procedure CreateParams(var Params: TCreateParams); override;
  1149.     procedure WndProc(var Message: TMessage); override;
  1150.   end;
  1151.  
  1152. procedure TRedirectorWindow.CreateParams(var Params: TCreateParams);
  1153. begin
  1154.   inherited CreateParams(Params);
  1155.   with Params do
  1156.   begin
  1157.     Style := WS_VISIBLE or WS_POPUP;
  1158.     WndParent := FFormHandle;
  1159.   end;
  1160. end;
  1161.  
  1162. procedure TRedirectorWindow.WndProc(var Message: TMessage);
  1163. begin
  1164.   inherited WndProc(Message);
  1165.   if (Message.Result = 0) and Assigned(FFindReplaceDialog) then
  1166.     Message.Result := Integer(FFindReplaceDialog.Message(Message));
  1167. end;
  1168.  
  1169. procedure TRedirectorWindow.CMRelease(var Message);
  1170. begin
  1171.   Free;
  1172. end;
  1173.  
  1174. { Find and Replace dialog routines }
  1175.  
  1176. function FindReplaceWndProc(Wnd: HWND; Msg, WParam, LParam: Longint): Longint; stdcall;
  1177.  
  1178.   function CallDefWndProc: Longint;
  1179.   begin
  1180.     Result := CallWindowProc(Pointer(GetProp(Wnd,
  1181.       MakeIntAtom(WndProcPtrAtom))), Wnd, Msg, WParam, LParam);
  1182.   end;
  1183.  
  1184. begin
  1185.   case Msg of
  1186.     WM_DESTROY:
  1187.       if Application.DialogHandle = Wnd then Application.DialogHandle := 0;
  1188.     WM_NCACTIVATE:
  1189.       if WParam <> 0 then
  1190.       begin
  1191.         if Application.DialogHandle = 0 then Application.DialogHandle := Wnd;
  1192.       end else
  1193.       begin
  1194.         if Application.DialogHandle = Wnd then Application.DialogHandle := 0;
  1195.       end;
  1196.     WM_NCDESTROY:
  1197.       begin
  1198.         Result := CallDefWndProc;
  1199.         RemoveProp(Wnd, MakeIntAtom(WndProcPtrAtom));
  1200.         Exit;
  1201.       end;
  1202.    end;
  1203.    Result := CallDefWndProc;
  1204. end;
  1205.  
  1206. function FindReplaceDialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
  1207. begin
  1208.   Result := DialogHook(Wnd, Msg, wParam, lParam);
  1209.   if Msg = WM_INITDIALOG then
  1210.   begin
  1211.     with TFindDialog(PFindReplace(LParam)^.lCustData) do
  1212.       if (Left <> -1) or (Top <> -1) then
  1213.         SetWindowPos(Wnd, 0, Left, Top, 0, 0, SWP_NOACTIVATE or
  1214.           SWP_NOSIZE or SWP_NOZORDER);
  1215.     SetProp(Wnd, MakeIntAtom(WndProcPtrAtom), GetWindowLong(Wnd, GWL_WNDPROC));
  1216.     SetWindowLong(Wnd, GWL_WNDPROC, Longint(@FindReplaceWndProc));
  1217.     Result := 1;
  1218.   end;
  1219. end;
  1220.  
  1221. const
  1222.   FindOptions: array[TFindOption] of Longint = (
  1223.     FR_DOWN, FR_FINDNEXT, FR_HIDEMATCHCASE, FR_HIDEWHOLEWORD,
  1224.     FR_HIDEUPDOWN, FR_MATCHCASE, FR_NOMATCHCASE, FR_NOUPDOWN, FR_NOWHOLEWORD,
  1225.     FR_REPLACE, FR_REPLACEALL, FR_WHOLEWORD, FR_SHOWHELP);
  1226.  
  1227. { TFindDialog }
  1228.  
  1229. constructor TFindDialog.Create(AOwner: TComponent);
  1230. begin
  1231.   inherited Create(AOwner);
  1232.   FOptions := [frDown];
  1233.   FPosition.X := -1;
  1234.   FPosition.Y := -1;
  1235.   with FFindReplace do
  1236.   begin
  1237.     lStructSize := SizeOf(TFindReplace);
  1238.     hWndOwner := Application.Handle;
  1239.     hInstance := SysInit.HInstance;
  1240.     lpstrFindWhat := FFindText;
  1241.     wFindWhatLen := SizeOf(FFindText);
  1242.     lpstrReplaceWith := FReplaceText;
  1243.     wReplaceWithLen := SizeOf(FReplaceText);
  1244.     lCustData := Longint(Self);
  1245.     lpfnHook := FindReplaceDialogHook;
  1246.   end;
  1247.   FFindReplaceFunc := @CommDlg.FindText;
  1248. end;
  1249.  
  1250. destructor TFindDialog.Destroy;
  1251. begin
  1252.   if FFindHandle <> 0 then SendMessage(FFindHandle, WM_CLOSE, 0, 0);
  1253.   FRedirector.Free;
  1254.   inherited Destroy;
  1255. end;
  1256.  
  1257. procedure TFindDialog.CloseDialog;
  1258. begin
  1259.   if FFindHandle <> 0 then PostMessage(FFindHandle, WM_CLOSE, 0, 0);
  1260. end;
  1261.  
  1262. function GetTopWindow(Wnd: THandle; var ReturnVar: THandle):Bool; stdcall;
  1263. var
  1264.   Test: TWinControl;
  1265. begin
  1266.   Test := FindControl(Wnd);
  1267.   Result := True;
  1268.   if Assigned(Test) and (Test is TForm) then
  1269.   begin
  1270.     ReturnVar := Wnd;
  1271.     Result := False;
  1272.    end;
  1273. end;
  1274.  
  1275. function TFindDialog.Execute: Boolean;
  1276. var
  1277.   Option: TFindOption;
  1278. begin
  1279.   if FFindHandle <> 0 then
  1280.   begin
  1281.     BringWindowToTop(FFindHandle);
  1282.     Result := True;
  1283.   end else
  1284.   begin
  1285.     HookCtl3D := Ctl3D;
  1286.     FFindReplace.Flags := FR_ENABLEHOOK;
  1287.     FFindReplace.lpfnHook := FindReplaceDialogHook;
  1288.     FRedirector := TRedirectorWindow.Create(nil);
  1289.     with TRedirectorWindow(FRedirector) do
  1290.     begin
  1291.       FFindReplaceDialog := Self;
  1292.       EnumThreadWindows(GetCurrentThreadID, @GetTopWindow, LPARAM(@FFormHandle));
  1293.     end;
  1294.     FFindReplace.hWndOwner := FRedirector.Handle;
  1295.     for Option := Low(Option) to High(Option) do
  1296.       if Option in FOptions then
  1297.         FFindReplace.Flags := FFindReplace.Flags or FindOptions[Option];
  1298.     if Template <> nil then
  1299.     begin
  1300.       FFindReplace.Flags := FFindReplace.Flags or FR_ENABLETEMPLATE;
  1301.       FFindReplace.lpTemplateName := Template;
  1302.     end;
  1303.     CreationControl := Self;
  1304.     FFindHandle := FFindReplaceFunc(FFindReplace);
  1305.     Result := FFindHandle <> 0;
  1306.   end;
  1307. end;
  1308.  
  1309. procedure TFindDialog.Find;
  1310. begin
  1311.   if Assigned(FOnFind) then FOnFind(Self);
  1312. end;
  1313.  
  1314. function TFindDialog.GetFindText: string;
  1315. begin
  1316.   Result := FFindText;
  1317. end;
  1318.  
  1319. function TFindDialog.GetLeft: Integer;
  1320. begin
  1321.   Result := Position.X;
  1322. end;
  1323.  
  1324. function TFindDialog.GetPosition: TPoint;
  1325. var
  1326.   Rect: TRect;
  1327. begin
  1328.   Result := FPosition;
  1329.   if FFindHandle <> 0 then
  1330.   begin
  1331.     GetWindowRect(FFindHandle, Rect);
  1332.     Result := Rect.TopLeft;
  1333.   end;
  1334. end;
  1335.  
  1336. function TFindDialog.GetReplaceText: string;
  1337. begin
  1338.   Result := FReplaceText;
  1339. end;
  1340.  
  1341. function TFindDialog.GetTop: Integer;
  1342. begin
  1343.   Result := Position.Y;
  1344. end;
  1345.  
  1346. function TFindDialog.Message(var Msg: TMessage): Boolean;
  1347. var
  1348.   Option: TFindOption;
  1349.   Rect: TRect;
  1350. begin
  1351.   Result := inherited Message(Msg);
  1352.   if not Result then
  1353.     if (Msg.Msg = FindMsg) and (Pointer(Msg.LParam) = @FFindReplace) then
  1354.     begin
  1355.       FOptions := [];
  1356.       for Option := Low(Option) to High(Option) do
  1357.         if (FFindReplace.Flags and FindOptions[Option]) <> 0 then
  1358.           Include(FOptions, Option);
  1359.       if (FFindReplace.Flags and FR_FINDNEXT) <> 0 then
  1360.         Find
  1361.       else
  1362.       if (FFindReplace.Flags and (FR_REPLACE or FR_REPLACEALL)) <> 0 then
  1363.         Replace
  1364.       else
  1365.       if (FFindReplace.Flags and FR_DIALOGTERM) <> 0 then
  1366.       begin
  1367.         GetWindowRect(FFindHandle, Rect);
  1368.         FPosition := Rect.TopLeft;
  1369.         FFindHandle := 0;
  1370.         PostMessage(FRedirector.Handle,CM_RELEASE,0,0); // free redirector later
  1371.         FRedirector := nil;
  1372.       end;
  1373.       Result := True;
  1374.     end;
  1375. end;
  1376.  
  1377. procedure TFindDialog.Replace;
  1378. begin
  1379.   if Assigned(FOnReplace) then FOnReplace(Self);
  1380. end;
  1381.  
  1382. procedure TFindDialog.SetFindText(const Value: string);
  1383. begin
  1384.   StrLCopy(FFindText, PChar(Value), SizeOf(FFindText) - 1);
  1385. end;
  1386.  
  1387. procedure TFindDialog.SetLeft(Value: Integer);
  1388. begin
  1389.   SetPosition(Point(Value, Top));
  1390. end;
  1391.  
  1392. procedure TFindDialog.SetPosition(const Value: TPoint);
  1393. begin
  1394.   if (FPosition.X <> Value.X) or (FPosition.Y <> Value.Y) then
  1395.   begin
  1396.     FPosition := Value;
  1397.     if FFindHandle <> 0 then
  1398.       SetWindowPos(FFindHandle, 0, Value.X, Value.Y, 0, 0,
  1399.         SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
  1400.   end;
  1401. end;
  1402.  
  1403. procedure TFindDialog.SetReplaceText(const Value: string);
  1404. begin
  1405.   StrLCopy(FReplaceText, PChar(Value), SizeOf(FReplaceText) - 1);
  1406. end;
  1407.  
  1408. procedure TFindDialog.SetTop(Value: Integer);
  1409. begin
  1410.   SetPosition(Point(Left, Value));
  1411. end;
  1412.  
  1413. { TReplaceDialog }
  1414.  
  1415. constructor TReplaceDialog.Create(AOwner: TComponent);
  1416. begin
  1417.   inherited Create(AOwner);
  1418.   FFindReplaceFunc := CommDlg.ReplaceText;
  1419. end;
  1420.  
  1421. { Message dialog }
  1422.  
  1423. function Max(I, J: Integer): Integer;
  1424. begin
  1425.   if I > J then Result := I else Result := J;
  1426. end;
  1427.  
  1428. function GetAveCharSize(Canvas: TCanvas): TPoint;
  1429. var
  1430.   I: Integer;
  1431.   Buffer: array[0..51] of Char;
  1432. begin
  1433.   for I := 0 to 25 do Buffer[I] := Chr(I + Ord('A'));
  1434.   for I := 0 to 25 do Buffer[I + 26] := Chr(I + Ord('a'));
  1435.   GetTextExtentPoint(Canvas.Handle, Buffer, 52, TSize(Result));
  1436.   Result.X := Result.X div 52;
  1437. end;
  1438.  
  1439.  
  1440. type
  1441.   TMessageForm = class(TForm)
  1442.   private
  1443.     procedure HelpButtonClick(Sender: TObject);
  1444.   public
  1445.     constructor CreateNew(AOwner: TComponent);
  1446.   end;
  1447.  
  1448. constructor TMessageForm.CreateNew(AOwner: TComponent);
  1449. var
  1450.   NonClientMetrics: TNonClientMetrics;
  1451. begin
  1452.   inherited CreateNew(AOwner);
  1453.   NonClientMetrics.cbSize := sizeof(NonClientMetrics);
  1454.   if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then
  1455.     Font.Handle := CreateFontIndirect(NonClientMetrics.lfMessageFont);
  1456. end;
  1457.  
  1458. procedure TMessageForm.HelpButtonClick(Sender: TObject);
  1459. begin
  1460.   Application.HelpContext(HelpContext);
  1461. end;
  1462.  
  1463. var
  1464.   Captions: array[TMsgDlgType] of string = (SMsgDlgWarning, SMsgDlgError,
  1465.     SMsgDlgInformation, SMsgDlgConfirm, '');
  1466.   IconIDs: array[TMsgDlgType] of PChar = (IDI_EXCLAMATION, IDI_HAND,
  1467.     IDI_ASTERISK, IDI_QUESTION, nil);
  1468.   ButtonNames: array[TMsgDlgBtn] of string = (
  1469.     'Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'NoToAll',
  1470.     'YesToAll', 'Help');
  1471.   ButtonCaptions: array[TMsgDlgBtn] of string = (
  1472.     SMsgDlgYes, SMsgDlgNo, SMsgDlgOK, SMsgDlgCancel, SMsgDlgAbort,
  1473.     SMsgDlgRetry, SMsgDlgIgnore, SMsgDlgAll, SMsgDlgNoToAll, SMsgDlgYesToAll,
  1474.     SMsgDlgHelp);
  1475.   ModalResults: array[TMsgDlgBtn] of Integer = (
  1476.     mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll, mrNoToAll,
  1477.     mrYesToAll, 0);
  1478.  
  1479. function CreateMessageDialog(const Msg: string; DlgType: TMsgDlgType;
  1480.   Buttons: TMsgDlgButtons): TForm;
  1481. const
  1482.   mcHorzMargin = 8;
  1483.   mcVertMargin = 8;
  1484.   mcHorzSpacing = 10;
  1485.   mcVertSpacing = 10;
  1486.   mcButtonWidth = 50;
  1487.   mcButtonHeight = 14;
  1488.   mcButtonSpacing = 4;
  1489. var
  1490.   DialogUnits: TPoint;
  1491.   HorzMargin, VertMargin, HorzSpacing, VertSpacing, ButtonWidth,
  1492.   ButtonHeight, ButtonSpacing, ButtonCount, ButtonGroupWidth,
  1493.   IconTextWidth, IconTextHeight, X: Integer;
  1494.   B, DefaultButton, CancelButton: TMsgDlgBtn;
  1495.   IconID: PChar;
  1496.   TextRect: TRect;
  1497. begin
  1498.   Result := TMessageForm.CreateNew(Application);
  1499.   with Result do
  1500.   begin
  1501.     BorderStyle := bsDialog;
  1502.     Canvas.Font := Font;
  1503.     DialogUnits := GetAveCharSize(Canvas);
  1504.     HorzMargin := MulDiv(mcHorzMargin, DialogUnits.X, 4);
  1505.     VertMargin := MulDiv(mcVertMargin, DialogUnits.Y, 8);
  1506.     HorzSpacing := MulDiv(mcHorzSpacing, DialogUnits.X, 4);
  1507.     VertSpacing := MulDiv(mcVertSpacing, DialogUnits.Y, 8);
  1508.     ButtonWidth := MulDiv(mcButtonWidth, DialogUnits.X, 4);
  1509.     ButtonHeight := MulDiv(mcButtonHeight, DialogUnits.Y, 8);
  1510.     ButtonSpacing := MulDiv(mcButtonSpacing, DialogUnits.X, 4);
  1511.     SetRect(TextRect, 0, 0, Screen.Width div 2, 0);
  1512.     DrawText(Canvas.Handle, PChar(Msg), Length(Msg), TextRect,
  1513.       DT_EXPANDTABS or DT_CALCRECT or DT_WORDBREAK);
  1514.     IconID := IconIDs[DlgType];
  1515.     IconTextWidth := TextRect.Right;
  1516.     IconTextHeight := TextRect.Bottom;
  1517.     if IconID <> nil then
  1518.     begin
  1519.       Inc(IconTextWidth, 32 + HorzSpacing);
  1520.       if IconTextHeight < 32 then IconTextHeight := 32;
  1521.     end;
  1522.     ButtonCount := 0;
  1523.     for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
  1524.       if B in Buttons then Inc(ButtonCount);
  1525.     ButtonGroupWidth := 0;
  1526.     if ButtonCount <> 0 then
  1527.       ButtonGroupWidth := ButtonWidth * ButtonCount +
  1528.         ButtonSpacing * (ButtonCount - 1);
  1529.     ClientWidth := Max(IconTextWidth, ButtonGroupWidth) + HorzMargin * 2;
  1530.     ClientHeight := IconTextHeight + ButtonHeight + VertSpacing +
  1531.       VertMargin * 2;
  1532.     Left := (Screen.Width div 2) - (Width div 2);
  1533.     Top := (Screen.Height div 2) - (Height div 2);
  1534.     if DlgType <> mtCustom then
  1535.       Caption := Captions[DlgType] else
  1536.       Caption := Application.Title;
  1537.     if IconID <> nil then
  1538.       with TImage.Create(Result) do
  1539.       begin
  1540.         Name := 'Image';
  1541.         Parent := Result;
  1542.         Picture.Icon.Handle := LoadIcon(0, IconID);
  1543.         SetBounds(HorzMargin, VertMargin, 32, 32);
  1544.       end;
  1545.     with TLabel.Create(Result) do
  1546.     begin
  1547.       Name := 'Message';
  1548.       Parent := Result;
  1549.       WordWrap := True;
  1550.       Caption := Msg;
  1551.       BoundsRect := TextRect;
  1552.       SetBounds(IconTextWidth - TextRect.Right + HorzMargin, VertMargin,
  1553.         TextRect.Right, TextRect.Bottom);
  1554.     end;
  1555.     if mbOk in Buttons then DefaultButton := mbOk else
  1556.       if mbYes in Buttons then DefaultButton := mbYes else
  1557.         DefaultButton := mbRetry;
  1558.     if mbCancel in Buttons then CancelButton := mbCancel else
  1559.       if mbNo in Buttons then CancelButton := mbNo else
  1560.         CancelButton := mbOk;
  1561.     X := (ClientWidth - ButtonGroupWidth) div 2;
  1562.     for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
  1563.       if B in Buttons then
  1564.         with TButton.Create(Result) do
  1565.         begin
  1566.           Name := ButtonNames[B];
  1567.           Parent := Result;
  1568.           Caption := ButtonCaptions[B];
  1569.           ModalResult := ModalResults[B];
  1570.           if B = DefaultButton then Default := True;
  1571.           if B = CancelButton then Cancel := True;
  1572.           SetBounds(X, IconTextHeight + VertMargin + VertSpacing,
  1573.             ButtonWidth, ButtonHeight);
  1574.           Inc(X, ButtonWidth + ButtonSpacing);
  1575.           if B = mbHelp then
  1576.             OnClick := TMessageForm(Result).HelpButtonClick;
  1577.         end;
  1578.   end;
  1579. end;
  1580.  
  1581. function MessageDlg(const Msg: string; DlgType: TMsgDlgType;
  1582.   Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
  1583. begin
  1584.   Result := MessageDlgPos(Msg, DlgType, Buttons, HelpCtx, -1, -1);
  1585. end;
  1586.  
  1587. function MessageDlgPos(const Msg: string; DlgType: TMsgDlgType;
  1588.   Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer): Integer;
  1589. begin
  1590.   with CreateMessageDialog(Msg, DlgType, Buttons) do
  1591.     try
  1592.       HelpContext := HelpCtx;
  1593.       if X >= 0 then Left := X;
  1594.       if Y >= 0 then Top := Y;
  1595.       Result := ShowModal;
  1596.     finally
  1597.       Free;
  1598.     end;
  1599. end;
  1600.  
  1601. procedure ShowMessage(const Msg: string);
  1602. begin
  1603.   ShowMessagePos(Msg, -1, -1);
  1604. end;
  1605.  
  1606. procedure ShowMessageFmt(const Msg: string; Params: array of const);
  1607. begin
  1608.   ShowMessage(Format(Msg, Params));
  1609. end;
  1610.  
  1611. procedure ShowMessagePos(const Msg: string; X, Y: Integer);
  1612. begin
  1613.   MessageDlgPos(Msg, mtCustom, [mbOK], 0, X, Y);
  1614. end;
  1615.  
  1616. { Input dialog }
  1617.  
  1618. function InputQuery(const ACaption, APrompt: string;
  1619.   var Value: string): Boolean;
  1620. var
  1621.   Form: TForm;
  1622.   Prompt: TLabel;
  1623.   Edit: TEdit;
  1624.   DialogUnits: TPoint;
  1625.   ButtonTop, ButtonWidth, ButtonHeight: Integer;
  1626. begin
  1627.   Result := False;
  1628.   Form := TForm.Create(Application);
  1629.   with Form do
  1630.     try
  1631.       Canvas.Font := Font;
  1632.       DialogUnits := GetAveCharSize(Canvas);
  1633.       BorderStyle := bsDialog;
  1634.       Caption := ACaption;
  1635.       ClientWidth := MulDiv(180, DialogUnits.X, 4);
  1636.       ClientHeight := MulDiv(63, DialogUnits.Y, 8);
  1637.       Position := poScreenCenter;
  1638.       Prompt := TLabel.Create(Form);
  1639.       with Prompt do
  1640.       begin
  1641.         Parent := Form;
  1642.         AutoSize := True;
  1643.         Left := MulDiv(8, DialogUnits.X, 4);
  1644.         Top := MulDiv(8, DialogUnits.Y, 8);
  1645.         Caption := APrompt;
  1646.       end;
  1647.       Edit := TEdit.Create(Form);
  1648.       with Edit do
  1649.       begin
  1650.         Parent := Form;
  1651.         Left := Prompt.Left;
  1652.         Top := MulDiv(19, DialogUnits.Y, 8);
  1653.         Width := MulDiv(164, DialogUnits.X, 4);
  1654.         MaxLength := 255;
  1655.         Text := Value;
  1656.         SelectAll;
  1657.       end;
  1658.       ButtonTop := MulDiv(41, DialogUnits.Y, 8);
  1659.       ButtonWidth := MulDiv(50, DialogUnits.X, 4);
  1660.       ButtonHeight := MulDiv(14, DialogUnits.Y, 8);
  1661.       with TButton.Create(Form) do
  1662.       begin
  1663.         Parent := Form;
  1664.         Caption := SMsgDlgOK;
  1665.         ModalResult := mrOk;
  1666.         Default := True;
  1667.         SetBounds(MulDiv(38, DialogUnits.X, 4), ButtonTop, ButtonWidth,
  1668.           ButtonHeight);
  1669.       end;
  1670.       with TButton.Create(Form) do
  1671.       begin
  1672.         Parent := Form;
  1673.         Caption := SMsgDlgCancel;
  1674.         ModalResult := mrCancel;
  1675.         Cancel := True;
  1676.         SetBounds(MulDiv(92, DialogUnits.X, 4), ButtonTop, ButtonWidth,
  1677.           ButtonHeight);
  1678.       end;
  1679.       if ShowModal = mrOk then
  1680.       begin
  1681.         Value := Edit.Text;
  1682.         Result := True;
  1683.       end;
  1684.     finally
  1685.       Form.Free;
  1686.     end;
  1687. end;
  1688.  
  1689. function InputBox(const ACaption, APrompt, ADefault: string): string;
  1690. begin
  1691.   Result := ADefault;
  1692.   InputQuery(ACaption, APrompt, Result);
  1693. end;
  1694.  
  1695. { Initialization and cleanup }
  1696.  
  1697. procedure InitGlobals;
  1698. var
  1699.   AtomText: array[0..31] of Char;
  1700. begin
  1701.   HelpMsg := RegisterWindowMessage(HelpMsgString);
  1702.   FindMsg := RegisterWindowMessage(FindMsgString);
  1703.   WndProcPtrAtom := GlobalAddAtom(StrFmt(AtomText,
  1704.     'WndProcPtr%.8X%.8X', [HInstance, GetCurrentThreadID]));
  1705. end;
  1706.  
  1707. initialization
  1708.   InitGlobals;
  1709. finalization
  1710.   if WndProcPtrAtom <> 0 then GlobalDeleteAtom(WndProcPtrAtom);
  1711. end.
  1712.